package com.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.zip.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import backpage.model.DBAccessor;

public class onDownload extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4125447885724694771L;

	/**
	 * Constructor of the object.
	 */
	public onDownload() {
		super();
	}

	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	@SuppressWarnings("deprecation")
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		if( request.getParameter("resID") != null ){	//down load one single file
			String resID = request.getParameter("resID");
			InputStream in = null;
			try{
				String srcFileName = DBAccessor.Instance.getResFullPathByID(Integer.parseInt(resID));
				if( srcFileName == null ){	//the record and the file were both deleted
					response.sendRedirect("resources.jsp?resType="+request.getParameter("resType")+"&download=fail");
					return;
				}
				
				String fileName = srcFileName.substring( srcFileName.lastIndexOf('/') + 1 );
				
				srcFileName = request.getRealPath(srcFileName);
				System.out.println(srcFileName);
				
				File file = new File(srcFileName);
				if( !file.exists() ){	//the file was lost, while the record in database still exists
					DBAccessor.Instance.deleteResByID(Integer.parseInt(resID));
					response.sendRedirect("resources.jsp?resType="+request.getParameter("resType")+"&download=fail");
					return;
				}
				
				in = new FileInputStream(file);
				
				response.reset();
				response.setContentType("application/force-download");
				response.addHeader("Content-Disposition",
						"attachment;filename="	//"attachment" means the data should be saved as an adjunct
													//while "inline" means open directly
						+ URLEncoder.encode( fileName, "utf-8" ) );
				response.addHeader("Content-Length", String.valueOf(file.length()));
				OutputStream out = response.getOutputStream();
				
				int fileSize = 0, n = 0;
				byte[] buffer = new byte[4096];
				while( ( n = in.read(buffer) ) > 0 ){
					fileSize += n;
					out.write( buffer, 0, n );
				}
				
				DBAccessor.Instance.incDownNum(resID);	//increase the download_num of this record
								
			}catch( Exception e ){
				System.err.println(e);
			}finally{
				if( in != null )
					in.close();
					in = null;
			}
						
		}
		
		else{
			ArchiveOutputStream archiveZipOut = null;
			try{
				response.reset();
				response.setContentType("application/force-download");
				response.addHeader("Content-Disposition","attachment;filename=default.zip");
				archiveZipOut = new ArchiveStreamFactory().createArchiveOutputStream(
						ArchiveStreamFactory.ZIP, response.getOutputStream());
				if( archiveZipOut instanceof ZipArchiveOutputStream )
					((ZipArchiveOutputStream)archiveZipOut).setEncoding("GBK");
				String[] checkValues = request.getParameterValues("itemCheckBox");
				byte[] buffer = new byte[4096];
				if( checkValues != null )
					for(int i=0; i<checkValues.length; i++){
						System.out.println(checkValues[i]);
						String srcFileName = DBAccessor.Instance.getResFullPathByID(Integer.parseInt(checkValues[i]));
						if( srcFileName == null ){	//the record and the file were both deleted
							continue;
						}
						String fileName = srcFileName.substring( srcFileName.lastIndexOf('/') + 1 );
						srcFileName = request.getRealPath(srcFileName);
						System.out.println(srcFileName);
						File file = new File(srcFileName);
						if( !file.exists() ){	//the file was lost, while the record in database still exist
							DBAccessor.Instance.deleteResByID(Integer.parseInt(checkValues[i]));
							continue;
						}
						ArchiveEntry archiveEntry = new ZipArchiveEntry( fileName );
						archiveZipOut.putArchiveEntry(archiveEntry);
						InputStream in = new FileInputStream(file);
						int n;
						while( ( n = in.read(buffer) ) > 0 )
							archiveZipOut.write(buffer,0,n);
						in.close();
						archiveZipOut.closeArchiveEntry();
						
						DBAccessor.Instance.incDownNum(checkValues[i]);//increase the download_num of this record
					}
			}catch(Exception e){
				System.err.println(e);
			}finally{
				if( archiveZipOut != null )
					archiveZipOut.close();
			}
		}
	}

	/**
	 * The doPost method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to post.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occurs
	 */
	public void init() throws ServletException {
		// Put your code here
	}

}
